home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / Resources / CutePDF 2.3 / converter.exe / GNUGS / PF2AFM.PS < prev    next >
Text File  |  2002-04-11  |  15KB  |  498 lines

  1. %!
  2. % This is a PostScript program for making an AFM file from
  3. % PFB / PFA and (optionally) PFM files.
  4. %
  5. % Written in BOP s.c., Gda\'nsk, Poland
  6. % e-mail contact: B.Jackowski@GUST.ORG.PL
  7. % version 0.5 (18 XII 1997)
  8. % version 0.55 (11 III 1998) -- unlimited number of chars in a font
  9. % version 1.00 (27 III 1998) -- scanning PFM subdirectory added,
  10. %                               code improved; version sent to LPD
  11. % version 1.01 (1 II 2000)   -- message changed
  12.  
  13. % $Id: pf2afm.ps,v 1.3.2.1 2002/04/10 09:22:58 giles Exp $
  14.  
  15. % Usage:
  16. %   gs [-dNODISPLAY] -- pf2afm.ps disk_font_name
  17. %
  18. % The result is written to the file disk_font_name.afm, provided such
  19. % a file does not exist; otherwise program quits.
  20. %
  21. % The font can be either *.pfa or *.pfb; if no extension is supplied,
  22. % first disk_font_name.pfb is examined, then disk_font_name.pfa.
  23. % Moreover, if there is a *.pfm file in the same directory or in the
  24. % subdirectory PFM, i.e., disk_font_name.pfm or PFM/disk_font_name.pfm,
  25. % kern pairs from it are extracted, as well as additional font
  26. % parameters, usually absent from Type 1 fonts.
  27.  
  28. % Tribute:
  29. % The program is based on James Clark's <jjc@jclark.uucp> printafm.ps
  30. % (with alterations by d.love@dl.ac.uk and L. Peter Deutsch) from
  31. % Ghostscript 5.10 distribution.
  32.  
  33. /onechar 1 string def
  34. /edef {exch def} def
  35.  
  36. % charnumber print-charname -
  37. % prints the name of the encoded character
  38. /print-charname {
  39.   PFBencoding exch get =string cvs dup
  40.   (.notdef) eq {
  41.     /was.notdef true def
  42.   } if
  43.   print.to.ofi ( ) print.to.ofi
  44. } def
  45.  
  46. /printquit {print flush quit} def
  47.  
  48. % redirecting GS output to ``ofi'' file
  49. /eolch (\r\n) def
  50. /=only.to.ofi {ofi exch write=only} def          % replaces GS's `=only'
  51. /print.to.ofi  {ofi exch writestring} def        % replaces `print'
  52. /=to.ofi { =only.to.ofi eolch print.to.ofi } def % replaces `='
  53.  
  54. % read and skip: byte, short, word, double and long
  55. /readb-p {currPFMfile read not {(Unexpected EOF) printquit} if} def
  56. /readw-p {readb-p readb-p 256 mul add} def
  57. /reads-p {readw-p dup 32768 ge {65536 sub} if} def
  58. /readd-p {readb-p readb-p readb-p readb-p 256 mul add 256 mul add 256 mul add} def
  59. /readl-p /readd-p load def % double word is, in fact, long integer in GS
  60. /skipb-p {readb-p pop} def
  61. /skipw-p {skipb-p skipb-p} def
  62. /skips-p /skipw-p load def
  63. /skipd-p {skipb-p skipb-p skipb-p skipb-p} def
  64. /skipl-p /skipd-p load def
  65. /skipa-p { {skipb-p} repeat} def
  66.  
  67. % PFMfile readPFMheader -
  68. % defines currPFMfile, PFMExtMetricOffset, PFMPairKernTableOffset
  69.  
  70. /readPFMheader {
  71.   currPFMfile bytesavailable
  72.   % ---------------
  73.   % PFM MAIN HEADER
  74.   % ---------------
  75.   skipw-p % PFM: version
  76.   readd-p % PFM: size (size is dword, not word as the documentation says)
  77.   ne {(Wrong file size) printquit} if
  78.   60 skipa-p  % PFM: copyright
  79.   skipw-p % PFM: Type
  80.   skipw-p % PFM: Points
  81.   skipw-p % PFM: VertRes
  82.   skipw-p % PFM: HorizRes
  83.   skipw-p % PFM: Ascent
  84.   skipw-p % PFM: InternalLeading
  85.   skipw-p % PFM: ExternalLeading
  86.   skipb-p % PFM: Italic
  87.   skipb-p % PFM: Underline
  88.   skipb-p % PFM: Stikeout
  89.   skipw-p % PFM: Weight
  90.   skipb-p % PFM: CharSet
  91.   skipw-p % PFM: PixWidth
  92.   skipw-p % PFM: PixHeight
  93.   skipb-p % PFM: PitchAndFamily
  94.   skipw-p % PFM: AvgWidth
  95.   skipw-p % PFM: MaxWidth
  96.   skipb-p % PFM: FirstChar
  97.   skipb-p % PFM: LastChar
  98.   skipb-p % PFM: DefaultChar
  99.   skipb-p % PFM: BreakChar
  100.   skipw-p % PFM: WidthBytes
  101.   skipd-p % PFM: Device
  102.   skipd-p % PFM: Face
  103.   skipd-p % PFM: BitsPointer
  104.   skipd-p % PFM: BitsOffset
  105.   % here we assume that it is a PostScript font, i.e., it always uses
  106.   % the extended width table, therefore the normal width table is empty
  107.   % -------------
  108.   % PFM EXTENSION
  109.   % -------------
  110.   skipw-p % PFMEX: SizeFields
  111.   readd-p % PFMEX: ExtMetricOffset
  112.     /PFMExtMetricOffset edef
  113.   skipd-p % PFMEX: ExtentTable
  114.   skipd-p % PFMEX: OriginTable
  115.   readd-p % PFMEX: PairKernTable
  116.     /PFMPairKernTableOffset edef
  117.   skipd-p % PFMEX: TrackKernTable
  118.   skipd-p % PFMEX: DriverInfo
  119.   skipd-p % PFMEX: Reserved
  120. } def
  121.  
  122. % requires that currPFMfile, PFMExtMetricOffset are defined
  123. % readPFMExtMetric -
  124. % defines PFMNumberofKernPairs
  125.  
  126. /readPFMExtMetric {
  127.   currPFMfile PFMExtMetricOffset setfileposition
  128.   skips-p % EXTT: Size
  129.   skips-p % EXTT: PointSize
  130.   skips-p % EXTT: Orientation
  131.   skips-p % EXTT: MasterHeight
  132.   skips-p % EXTT: MinScale
  133.   skips-p % EXTT: MaxScale
  134.   skips-p % EXTT: MasterUnit
  135.   reads-p % EXTT: CapHeight
  136.    /PFMCapHeight edef
  137.   reads-p % EXTT: XHeight
  138.    /PFMXHeight edef
  139.   reads-p % EXTT: LowerCaseAscent
  140.    /PFMLowerCaseAscent edef
  141.   reads-p % EXTT: LowerCaseDescent
  142.    neg /PFMLowerCaseDescent edef
  143.   skips-p % EXTT: Slant
  144.   skips-p % EXTT: SuperScript
  145.   skips-p % EXTT: SubScript
  146.   skips-p % EXTT: SuperScriptSize
  147.   skips-p % EXTT: SubScriptSize
  148.   skips-p % EXTT: UnderlineOffset
  149.   skips-p % EXTT: UnderlineWidth
  150.   skips-p % EXTT: DoubleUpperUnderlineOffset
  151.   skips-p % EXTT: DoubleLowerUnderlineOffset
  152.   skips-p % EXTT: DoubleUpperUnderlineWidth
  153.   skips-p % EXTT: DoubleLowerUnderlineWidth
  154.   skips-p % EXTT: StrikeOutOffset
  155.   skips-p % EXTT: StrikeOutWidth
  156.   readw-p % EXTT: KernPairs
  157.     /PFMNumberofKernPairs edef
  158.   skipw-p % EXTT: KernTracks
  159. } def
  160.  
  161. % requires that currPFMfile, PFMPairKernTableOffset, PFMNumberofKernPairs are defined
  162. % readPFMExtMetric -
  163. % prints kern pairs table in the AFM format
  164.  
  165. /readPFMKernPairs {
  166.   currPFMfile () ne {
  167.     PFMdict begin
  168.     PFMPairKernTableOffset 0 ne {
  169.       currPFMfile PFMPairKernTableOffset setfileposition
  170.       readw-p % undocumented kern count (although all remaining structures are
  171.               % explicitly preceded by their sizes); if it were a stable
  172.              % feature, EXTTEXTMETRICS could be skipped
  173.       PFMNumberofKernPairs
  174. %     2 copy = =
  175.       ne {
  176.         (Inconsistent number of kern pairs) printquit
  177.       } if
  178.       (StartKernData) =to.ofi
  179.       (StartKernPairs ) print.to.ofi
  180.       PFMNumberofKernPairs =to.ofi
  181.       % ---------
  182.       % MAIN LOOP
  183.       % ---------
  184.       /was.notdef false def
  185.       PFMNumberofKernPairs {
  186.         (KPX ) print.to.ofi
  187.         readb-p  % first  char
  188.         print-charname
  189.         readb-p  % second char
  190.         print-charname
  191.         reads-p  % kern amount
  192.         =to.ofi
  193.       } repeat
  194.       was.notdef {
  195.         (.notdef character ocurred among kern pairs) =
  196.         (you'd better check the resulting AFM file.) =
  197.       } if
  198.       (EndKernPairs) =to.ofi
  199.       (EndKernData)  =to.ofi
  200.     } if
  201.     end
  202.   } if
  203. } def
  204.  
  205. % alias (for ``compatibility'' with J. Clark):
  206. /printkernpairs /readPFMKernPairs load def
  207.  
  208. % printcharmetrics -
  209.  
  210. /printcharmetrics {
  211.   (StartCharMetrics ) print.to.ofi
  212.   /PFBencoding currfont /Encoding get dup length array copy def
  213.   /PFBcharstrings currfont /CharStrings get def
  214.   PFBcharstrings length
  215.   PFBcharstrings /.notdef known { 1 sub } if =to.ofi
  216.   currfont 1000 scalefont setfont
  217.   % checking Encoding array and CharStrings dictionary for
  218.   % the consistency of names
  219.   /was.inconsitent false def
  220.   0 1 255 {
  221.     dup PFBencoding exch get
  222.     PFBcharstrings exch known {
  223.       pop
  224.     }{
  225. %     dup PFBencoding exch get =
  226.       PFBencoding exch /.notdef put % fix Encoding array
  227.       /was.inconsitent true def
  228.     } ifelse
  229.   } for
  230.   was.inconsitent {
  231.     (Encoding array contains name(s) absent from CharStrings dictionary) =
  232.   } if
  233.   % print metric data for each character in PFB encoding vector
  234.   0 1 255 {
  235.     dup PFBencoding exch get
  236.     dup /.notdef ne {
  237.       exch dup printmetric
  238.     }{
  239.       pop pop
  240.     } ifelse
  241.   } for
  242.   % xPFBencoding contains an entry for each name in the original
  243.   % encoding vector
  244.   /xPFBencoding PFBcharstrings length dict def
  245.   PFBencoding {
  246.     xPFBencoding exch true put
  247.   } forall
  248.  
  249.   /fontiter 0 def
  250.   /TMPFontTemplate (TMP_FONT#000) def
  251.   {
  252.     % NewPFBencoding is the new encoding vector
  253.     /NewPFBencoding 256 array def
  254.     0 1 255 {
  255.       NewPFBencoding exch /.notdef put
  256.     } for
  257.     % fill up NewPFBencoding with names from CharStrings dictionary that
  258.     % are not encoded so far
  259.     /i 0 def
  260.     PFBcharstrings {
  261.       pop
  262.       i 255 le {
  263.         dup xPFBencoding exch known not {
  264.           dup xPFBencoding exch true put
  265.           NewPFBencoding i 3 -1 roll put
  266.           /i i 1 add def
  267.         }{
  268.           pop
  269.         } ifelse
  270.       }{
  271.         pop exit
  272.       } ifelse
  273.     } forall
  274.     i 0 eq {exit} if
  275.     % define a new font with NewPFBencoding as its encoding vector
  276.     currfont maxlength dict /NewTMPfont edef
  277.     currfont {
  278.       exch dup dup /FID ne exch /Encoding ne and {
  279.         exch NewTMPfont 3 1 roll put
  280.       }{
  281.         pop pop
  282.       } ifelse
  283.     } forall
  284.     % compute a unique name for a font to be registered
  285.     /fontiter fontiter 1 add def
  286.     TMPFontTemplate fontiter (000) cvs
  287.     dup length TMPFontTemplate length exch sub exch putinterval
  288.     /TMPFontName TMPFontTemplate cvn def
  289.     NewTMPfont /FontName TMPFontName put
  290.     NewTMPfont /Encoding NewPFBencoding put
  291.     % make this new font the current font
  292.     TMPFontName NewTMPfont definefont 1000 scalefont setfont
  293.     % print metric data for each character in the newly created encoding vector
  294.     0 1 255 {
  295.       dup NewPFBencoding exch get
  296.       dup /.notdef ne {
  297.         exch -1 printmetric
  298.       }{
  299.         pop pop exit
  300.       } ifelse
  301.     } for
  302.   i 255 lt {exit} if
  303.   } loop
  304.   (EndCharMetrics) =to.ofi
  305. } def
  306.  
  307. % name actual_code normal_code printmetric -
  308.  
  309. /printmetric {
  310.   (C ) print.to.ofi =only.to.ofi
  311.   ( ; WX ) print.to.ofi
  312.   onechar 0 3 -1 roll put
  313.   onechar stringwidth pop round cvi =only.to.ofi
  314.   ( ; N ) print.to.ofi =only.to.ofi
  315.   ( ; B ) print.to.ofi
  316.   newpath 0 0 moveto
  317.   onechar false charpath flattenpath pathbbox
  318.   newpath
  319.   round cvi /ury edef round cvi /urx edef
  320.   round cvi /lly edef round cvi /llx edef
  321.   ury lly eq {/ury 0 def /lly 0 def} if % normalize degenrated BB
  322.   urx llx eq {/urx 0 def /llx 0 def} if %
  323.   llx =only.to.ofi ( ) print.to.ofi lly =only.to.ofi ( ) print.to.ofi
  324.   urx =only.to.ofi ( ) print.to.ofi ury =only.to.ofi ( ) print.to.ofi
  325.   (;) =to.ofi
  326. } def
  327.  
  328. /printinfoitem {
  329.   3 1 roll 2 copy known {
  330.     get =string cvs exch
  331.     print.to.ofi ( ) print.to.ofi =to.ofi
  332.   }{
  333.     pop pop pop
  334.   } ifelse
  335. } def
  336.  
  337. /printfontinfo {
  338.   (Comment AFM Generated by Ghostscript/pf2afm) =to.ofi
  339.   currfont /FontName  (FontName) printinfoitem
  340.   %
  341.   currfont /FontInfo get
  342.   dup /FullName           (FullName)           printinfoitem
  343.   dup /FamilyName         (FamilyName)         printinfoitem
  344.   dup /Weight             (Weight)             printinfoitem
  345.   dup /Notice             (Notice)             printinfoitem
  346.   dup /ItalicAngle        (ItalicAngle)        printinfoitem
  347.   dup /isFixedPitch       (IsFixedPitch)       printinfoitem
  348.   dup /UnderlinePosition  (UnderlinePosition)  printinfoitem
  349.   dup /UnderlineThickness (UnderlineThickness) printinfoitem
  350.       /version            (Version)            printinfoitem
  351.   %
  352.   (EncodingScheme FontSpecific) =to.ofi
  353.   %
  354.   (FontBBox) print.to.ofi
  355.   currfont /FontBBox get {
  356.     ( ) print.to.ofi round cvi =only.to.ofi
  357.   } forall
  358.   eolch print.to.ofi
  359.   %
  360.   currPFMfile () ne {
  361.     PFMdict
  362.     dup /PFMCapHeight        (CapHeight) printinfoitem
  363.     dup /PFMXHeight          (XHeight)   printinfoitem
  364.     dup /PFMLowerCaseDescent (Descender) printinfoitem
  365.         /PFMLowerCaseAscent  (Ascender)  printinfoitem
  366.   } if
  367. } def
  368.  
  369. /readPFBfile {
  370.   % make a shot of the actual font directory:
  371.   /oldFontDirectory FontDirectory dup length dict copy def
  372.   isPFB {% defined in `makeafm'
  373.     (r) file true /PFBDecode filter cvx % true is better (see gs_type1.ps)
  374.     mark exch exec
  375.   }{
  376.     (r) file mark exch run
  377.   } ifelse
  378.   cleartomark
  379.   % make a shot of the updated font directory:
  380.   /newFontDirectory FontDirectory dup length dict copy def
  381.   % spot the added font:
  382.   oldFontDirectory  {pop newFontDirectory exch undef} forall
  383.   newFontDirectory length 1 ne {
  384.     newFontDirectory length =
  385.     (Weird PFB file?) printquit
  386.   } if
  387.   newFontDirectory {pop} forall
  388.   findfont /currfont edef
  389. } def
  390.  
  391. /readPFMfile {
  392.   dup () ne {
  393.     (r) file /currPFMfile edef
  394.     10 dict dup /PFMdict edef begin
  395.     readPFMheader
  396.     readPFMExtMetric
  397.     end
  398.   }{
  399.     pop /currPFMfile () def
  400.   } ifelse
  401. } def
  402.  
  403. % pfmfilename pf[ba]filename filetype printafm -
  404. % where filetype=(a) or (b)
  405.  
  406. /printafm {
  407.   readPFBfile
  408.   readPFMfile
  409.   (StartFontMetrics 2.0) =to.ofi
  410.   printfontinfo
  411.   printcharmetrics
  412.   printkernpairs
  413.   (EndFontMetrics) =to.ofi
  414. } def
  415.  
  416. % pf[ba]filename makeafm -
  417.  
  418. /makeafm {
  419.   count 0 eq {(Missing font file name) printquit} if
  420.   /ifn edef
  421.   ifn length 0 eq {(Empty font file name) printquit} if
  422. % the following piece of the code does, in fact, the job of a system shell,
  423. % i.e., it analyses the supplied names, appends extensions if needed,
  424. % and check files:
  425.   /pfbn () def /pfan () def /pfmn () def % initialisation
  426.   ifn (.pfb) search {
  427.     3 -1 roll length 0 eq {% file name extension = ".pfb"
  428.       ifn dup length string copy /pfbn edef
  429.       /ifn edef
  430.     }{pop} ifelse
  431.   } if pop
  432.   ifn (.pfa) search {
  433.     3 -1 roll length 0 eq {% file name extension = ".pfa"
  434.       ifn dup length string copy /pfan edef
  435.       /ifn edef
  436.     }{pop} ifelse
  437.   } if pop
  438.   pfbn () eq pfan () eq and dup {% no extension was supplied, try ".pfb"
  439.     /pfbn ifn (.pfb) concatstrings def
  440.   } if
  441.   pfbn () ne {% check whether "filename.pfb" exists
  442.     pfbn status {pop pop pop pop /isPFB true def}{/pfbn () def} ifelse
  443.   } if
  444.   pfbn () eq and {% checking "filename.pfb" unsuccessful, try ".pfa"
  445.     /pfan ifn (.pfa) concatstrings def
  446.   } if
  447.   pfan () ne {% check whether "filename.pfa" exists
  448.     pfan status {pop pop pop pop /isPFB false def}{/pfan () def} ifelse
  449.   } if
  450.  
  451.   pfbn () eq pfan () eq and {
  452.     (Neither pfa nor pfb found) printquit
  453.   } if
  454.  
  455.   /ofn ifn (.afm) concatstrings def
  456.   ofn status {
  457.     pop pop pop pop (Resulting file exists) printquit
  458.   } if
  459.   /ofi ofn (w) file def
  460.   //systemdict /.setsafe known { .setsafe } if
  461.  
  462.   /pfmn ifn (.pfm) concatstrings def
  463.   pfmn status {
  464.     pop pop pop pop
  465.   }{
  466.     () pfmn {
  467.       (/) search {
  468.         4 -1 roll exch concatstrings exch concatstrings exch
  469.       }{
  470.         exit
  471.       } ifelse
  472.     } loop
  473.     (pfm/) exch concatstrings concatstrings
  474.     dup status {
  475.       pop pop pop pop /pfmn edef
  476.     }{
  477.       pop /pfmn () def (pfm file not found -- ignored) print
  478.     } ifelse
  479.   } ifelse
  480.  
  481.   pfmn
  482.   isPFB {pfbn}{pfan} ifelse
  483.   printafm
  484.  
  485. } def
  486.  
  487. % Check for command line arguments.
  488. [ shellarguments
  489.   { ] dup length 1 eq {
  490.        0 get makeafm
  491.      }{
  492.        (This is PF2AFM -- AFM generator \(ver. 1.00\)\n)
  493.        (Usage: gs [-dNODISPLAY] -- pf2afm.ps disk_font_name\n) printquit
  494.      } ifelse
  495.   }
  496.   {pop}
  497. ifelse
  498.